module ysyx_22040339_LSU(
    input clk,
    input [63:0] addr,
    input [63:0] pc,
    input [2:0] size,
    input wen,
    input [63:0] wdata,
    output [63:0] rdata,
    output [31:0] inst
);

//    reg [63:0] ram [0:16383];
    reg [7:0] ram [0:524287];
    
    wire [63:0] inst_addr = (pc - 64'h80000000);

    wire unsigned_read = size[2];
    wire [7:0] wmask;
    wire [7:0] temp_rdata1;
    wire [7:0] temp_rdata2;
    wire [7:0] temp_rdata3;
    wire [7:0] temp_rdata4;
    wire [7:0] temp_rdata5;
    wire [7:0] temp_rdata6;
    wire [7:0] temp_rdata7;
    wire [7:0] temp_rdata8;
    wire [63:0] temp_rdata;
    wire [63:0] s_byte_rdata;
    wire [63:0] u_byte_rdata;
    wire [63:0] byte_rdata;
    wire [63:0] s_half_rdata;
    wire [63:0] u_half_rdata;
    wire [63:0] half_rdata;
    wire [63:0] s_word_rdata;
    wire [63:0] u_word_rdata;
    wire [63:0] word_rdata;
    wire [63:0] rw_addr = (addr - 64'h80000000);
    
    assign inst =  {ram[inst_addr + 64'h3],ram[inst_addr + 64'h2],ram[inst_addr + 64'h1],ram[inst_addr]};

    assign wmask = (size[1:0] == 2'b00) ? 8'h1 : ((size[1:0] == 2'b01) ? 8'h3 : ((size[1:0] == 2'b10) ? 8'hF : 8'hFF));

/*    integer initvar;
    initial begin
      for (initvar = 0; initvar < 524288; initvar = initvar+1)
        ram[initvar] = 8'b0;
    end
*/
   initial $readmemh("/home/chenkang/testcase.hex/wanshu-riscv64-nemu.hex",ram);

    always @(posedge clk) begin
        if(wen) begin
            if(wmask[0]) ram[rw_addr] <= wdata[7:0];
            if(wmask[1]) ram[rw_addr + 64'h1] <= wdata[15:8];
            if(wmask[2]) ram[rw_addr + 64'h2] <= wdata[23:16];
            if(wmask[3]) ram[rw_addr + 64'h3] <= wdata[31:24];
            if(wmask[4]) ram[rw_addr + 64'h4] <= wdata[39:32];
            if(wmask[5]) ram[rw_addr + 64'h5] <= wdata[47:40];
            if(wmask[6]) ram[rw_addr + 64'h6] <= wdata[55:48];
            if(wmask[7]) ram[rw_addr + 64'h7] <= wdata[63:56];
        end
    end    
    
    assign temp_rdata1 = ram[rw_addr];
    assign temp_rdata2 = ram[rw_addr + 64'h1];
    assign temp_rdata3 = ram[rw_addr + 64'h2];
    assign temp_rdata4 = ram[rw_addr + 64'h3];
    assign temp_rdata5 = ram[rw_addr + 64'h4];
    assign temp_rdata6 = ram[rw_addr + 64'h5];
    assign temp_rdata7 = ram[rw_addr + 64'h6];
    assign temp_rdata8 = ram[rw_addr + 64'h7];
    assign temp_rdata = {temp_rdata8,temp_rdata7,temp_rdata6,temp_rdata5,temp_rdata4,temp_rdata3,temp_rdata2,temp_rdata1};

    assign s_byte_rdata = {{56{temp_rdata[7]}},temp_rdata[7:0]};
    assign u_byte_rdata = {56'b0,temp_rdata[7:0]};
    assign byte_rdata = unsigned_read ? u_byte_rdata : s_byte_rdata;

    assign s_half_rdata = {{48{temp_rdata[15]}},temp_rdata[15:0]};
    assign u_half_rdata = {48'b0,temp_rdata[15:0]};
    assign half_rdata = unsigned_read ? u_half_rdata : s_half_rdata;

    assign s_word_rdata = {{32{temp_rdata[31]}},temp_rdata[31:0]};
    assign u_word_rdata = {32'b0,temp_rdata[31:0]};
    assign word_rdata = unsigned_read ? u_word_rdata : s_word_rdata;

    assign rdata = (size[1:0] == 2'b0) ? byte_rdata : ((size[1:0] == 2'b1) ? half_rdata : ((size[1:0] == 2'b10) ? word_rdata : temp_rdata));

endmodule
    
